#pragma once

#ifndef SOCKET5_H
#define SOCKET5_h

#include <event2/event.h>
#include <event2/util.h>

#define VERSION_SOCKET4 0x04
#define VERSION_SOCKET5 0x05

#define AUTH_NONE 0x00
#define AUTH_GSSAPI 0x01
#define AUTH_USER	0x02

#define CMD_CONNECT 0x01
#define CMD_BIND 0x02
#define CMD_UDP 0x03

#define ATYP_IPV4 0x01
#define ATYP_DOMAIN 0x03
#define ATYP_IPV6 0x04

#define METHOD_NONE 0x00
#define METHOD_GSSAPI 0x01
#define METHOD_USERNAME_PASSWORD 0x02
#define METHOD_REJECT 0xff
#define METHOD_ALLOW_NONE 1

#define AUTH_NAME_DEFAULT "hch"
#define AUTH_PWD_DEFAULT "hch666666"

#define BUFFER_SIZE 4096

typedef struct _method_select_response
{
	char version;
	char select_method;
}METHOD_SELECT_RESPONSE;

typedef struct _method_select_request
{
	char version;
	char number_methods;
	char methods[255];
}METHOD_SELECT_REQUEST;

typedef struct _AUTH_RESPONSE
{
	char version;	//0x01
	char result;
}AUTH_RESPONSE;

typedef struct _AUTH_REQUEST
{
	char version;	//0x01
	char name_len;
	char name[255];
	char pwd_len;
	char pwd[255];
}AUTH_REQUEST;

typedef struct _SOCKET5_RESPONSE
{
	char version; //0x04 0x05
	char reply;
	char reserved;	//0x00
	char address_type;	//IPV4 0x01 IPV6 0x04 domain 0x03
	char address_port[1];
}SOCKET5_RESPONSE;

typedef struct _SOCKET5_REQUEST
{
	char version;
	char cmd;	//connect 0x01	BIND 0x02	UDP 0x03
	char reserved;	//0x00
	char address_type;
}SOCKET5_REQUEST;

typedef struct _SOCKET5_CLIENT
{
	evutil_socket_t socket;
	evutil_socket_t remote_socket;
	event * read_event;
	event * timeout_event;
	event* remote_read_event;
	event* remote_timeout_event;
} client;

client* client_new();
void client_release(client* user);

void client_select_method(evutil_socket_t socket, short event, void* arg);
void client_auth_none(evutil_socket_t socket, short event, void* arg);
void client_auth_name_pwd(evutil_socket_t socket, short event, void* arg);
void client_auth_gssapi(evutil_socket_t socket, short event, void* arg);
void parse_commond(evutil_socket_t socket, short event, void* arg);
void remote_read_event_callback(evutil_socket_t socket, short event, void* arg);
void remote_timeout_event_callback(evutil_socket_t socket, short event, void* arg);

#endif
